/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package treegenerator.gui;

import com.jme3.gde.core.scene.OffScenePanel;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

/**
 *
 * @author jannes
 */
public class OffScenePanelWithMovement extends OffScenePanel{
    private ArrayList<Spatial> attachedSpatials;
    private long nextMovement;       
    public OffScenePanelWithMovement(int width, int height){
        super(width,height);
        attachedSpatials = new ArrayList<Spatial>();
        nextMovement = 0;   
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                requestFocus();                
            }
        });        
        addKeyListener(new KeyAdapter() {            
            @Override
            public void keyPressed(KeyEvent ke) {                
                if(System.currentTimeMillis() > nextMovement){
                    if(ke.isControlDown()){                                                
                        if(ke.getKeyCode() == KeyEvent.VK_UP){                                                              
                            rotate(0.05f, true);                                              
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_DOWN){
                            rotate(-0.05f, true);                                              
                            nextMovement = System.currentTimeMillis() + 50;
                        }
                        if(ke.getKeyCode() == KeyEvent.VK_LEFT){                                                                                            
                            rotate(0.05f, false);
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_RIGHT){                        
                            rotate(-0.05f, false);
                            nextMovement = System.currentTimeMillis() + 50;
                        }                        
                    }else if(ke.isAltDown()){
                        if(ke.getKeyCode() == KeyEvent.VK_UP){    
                            strafe(0.1f, true);
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_DOWN){
                            strafe(-0.1f, true);
                            nextMovement = System.currentTimeMillis() + 50;
                        }
                        if(ke.getKeyCode() == KeyEvent.VK_LEFT){                                                                                            
                            strafe(0.1f, false);
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_RIGHT){                        
                            strafe(-0.1f, false);
                            nextMovement = System.currentTimeMillis() + 50;
                        }
                    }else{
                        if(ke.getKeyCode() == KeyEvent.VK_UP){                                                                    
                            moveCamera(0.1f);                    
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_DOWN){
                            moveCamera(-0.1f);                    
                            nextMovement = System.currentTimeMillis() + 50;
                        }
                        if(ke.getKeyCode() == KeyEvent.VK_LEFT){                                                                                            
                            rotateCamera(getCamera().getUp(), 0.05f);
                            nextMovement = System.currentTimeMillis() + 50;
                        }else if(ke.getKeyCode() == KeyEvent.VK_RIGHT){                        
                            rotateCamera(getCamera().getUp(), -0.05f);
                            nextMovement = System.currentTimeMillis() + 50;
                        }
                    }
                }
            }            
        });                
    }               
    
    public void strafe(float distance, boolean upDown){
        Camera camera = getCamera();
        Vector3f axis = null;
        if(upDown){
            axis = camera.getUp();            
        }else{
            axis = camera.getLeft();
        }        
        Vector3f location = camera.getLocation();
        location = location.add(axis.mult(distance));
        camera.setLocation(location);
        camera.update();
    }
        
    
    public void rotate(float amount, boolean upDown){
       Camera camera = getCamera();
       Vector3f upAxis = camera.getUp();
       Vector3f leftAxis = camera.getLeft();
       Vector3f forwardAxis = camera.getDirection();       
       Vector3f location = camera.getLocation();
       if(upDown){
           location = location.add(forwardAxis).add(upAxis.mult(amount));
       }else{
           location = location.add(forwardAxis).add(leftAxis.mult(amount));
       }
        
       camera.lookAt(location, new Vector3f(0,1f,0));   
       camera.update();
    }
        
    @Override
    public void startPreview(){
        super.startPreview();
        while(getCamera() == null){
            try{
                Thread.sleep(100l);
            }catch(Exception exc){}
        }
        getCamera().setLocation(new Vector3f(0f,0f,0f));
    }
    
    @Override
    public void attach(Spatial spatial){
        super.attach(spatial);
        attachedSpatials.add(spatial);
    }
    
    @Override
    public void cleanup(){
        super.cleanup();
        for(Spatial s : attachedSpatials){
            detach(s);
        }
        attachedSpatials.clear();
    }
}
